# -*- encoding: utf-8 -*- 
""" CzechTV plugin for accessing www.ceskatelevize.cz videos from XBMC """

__all__ = ["CzechtvPlugin"]

from lib.basePlugin import *
import re
import time
import datetime

DATE_FORMAT = '%d.%m.%Y'
DAY_NAME = (u'Po', u'Út', u'St', u'Čt', u'Pá', u'So', u'Ne')

RE_DATE   = re.compile('(\d{1,2}\.\s*\d{1,2}\.\s*\d{4})')
RE_RATING = re.compile('width:\s*(\d+)%')
RE_PGNUM  = re.compile('/(\d+)/?$')


def date2label(date):
    """ Generate label for date """
    dayname = DAY_NAME[date.weekday()]
    return "%s %s.%s.%s" % (dayname, date.day, date.month, date.year)


def get_pg_num(path):
    """ Get page number from url/path """
    m = RE_PGNUM.search(path)
    if m:
        return m.group(1)

    
class CzechTVProgram:
    LOGPREFIX = "[CzechTV plugin] "
    bonusy = False
    bonusyPath = None

    def __init__(self, api, path):
        self.api = api
        self.path = path

        if '/bonusy' in self.path:
            self.bonusy = True
        elif '/dalsi-casti' not in self.path:
            self.path = re.sub(r'/*(?=([?].*)?$)', '/dalsi-casti', self.path, 1)
            self.path = self.path.replace('//','/')

        self.api.wget.request(self.api.BASE_URL + self.path)
        self.page = self.api.wget.select('div#mainPage')
        if not self.page:
            raise Exception('div#mainPage not found')

        if not self.bonusy:
            a = self.page.select_first('a#linkAjax__bonusy')
            if a:
                self.bonusyPath = a['href']

        self.info_div = self.api.wget.select('div#programmeInfoBlock') \
                        or self.api.wget.select('div#programmeInfoBlock2')
        if not self.info_div:
            raise Exception('div#programmeInfoBlock not found')


    def getInfo(self):
        info = {
                'title': self.info_div.select_first('#programmeInfo h2').text.strip(),
                'plotoutline': unicode(self.info_div.select_first('div#programmeInfo h2 + p').contents[0]).strip(),
                'plot': self.info_div.select_first('#programmeInfoDetail p').text.strip(),
                'genre': self.info_div.select_first('#programmeInfoDetail a.loadProgrammeGenre').text,
            }
        # add date 
        m = RE_DATE.search( self.info_div.select('#programmeInfoDetail p')[1].text )
        if m:
            info['date'] = m.group(1)
        # add rating value: 
        rating = self.info_div.select_first('#programmeDetailRatingRating')
        if rating:
            m = RE_RATING.search( rating.get('style', '') )
            if m:
                info['rating'] = float(m.group(1)) / 100.0
        # icon url 
        img = self.info_div.select_first('#programmeInfo > div > p.dNone > img')
        optargs = {}
        if img:
            optargs['iconURL'] = img['src']
        # label 
        label = info['title']
        if info['plotoutline']:
            label += ' - ' + info['plotoutline']

        if u'Vybraná část není v iVysílání k dispozici.' in info['plotoutline']:
            return None

        return PItem(label,
                    info=info, 
                    call='play',
                    param={'path': self.path},
                    **optargs
                )


    def getEpizodeList(self):
        content = self.info_div.select('#programmeContent')
        list_title = u'Další části'
        if self.bonusy:
            list_title = u'Bonusy'
        h2 = content.select_first('h2')
        if h2 and h2.text == list_title:
            for item in content.select('li'):
                # description
                plotoutline = ''
                for p in item.select('p'):
                    if p.text and not p.get('class') and p.contents:
                        plotoutline += ' ' + unicode(p.contents[0]).strip()

                h3_a = item.select_first('h3 a')
                info = {
                        'title': h3_a.text.strip(),
                        'plotoutline': plotoutline.strip(),
                    }
                # add date 
                m = RE_DATE.search( info['title'] )
                if m:
                    info['date'] = m.group(1)
                # add rating value: 
                rating = item.select_first('.programmeItemRatingStarMini')
                if rating:
                    m = RE_RATING.search( rating['style'] )
                    if m:
                        info['rating'] = float(m.group(1)) / 100.0
                # icon url 
                img = item.select_first('.foto img')
                optargs = {}
                if img:
                    optargs['iconURL'] = img['src']
                # label 
                label = info['title']
                if info['plotoutline']:
                    label += ' - ' + info['plotoutline']

                yield PItem(label,
                            info=info,
                            call='play',
                            param={'path': h3_a['href']},
                            **optargs
                        )


    def getPageLinks(self):
        links = self.info_div.select('.pagingContent td a.detailProgrammePaging')
        links = [ e['href'] for e in links ]
        out = {}
        if links:
            if re.search(r'/(dalsi-casti|bonusy)/?$', links[0]):
                out['first'] = links[0]
                out['prev']  = links[1]
            if not re.search(r'/(dalsi-casti|bonusy)/?$', links[-2]):
                out['next']  = links[-2]
                out['last']  = links[-1]
        return out


    def playlistURL(self):
        obj = self.page.select_first('#programmeObject embed')
        if not obj:
            raise Exception("playlistURL not found!\n Path: %r, Page content:\n%s"
                                % (self.path, self.page) )
        url = obj['src'] or obj['data']
        if url:
            return url
        raise Exception("playlistURL not found!\n obj: " + repr(obj)) 


    def getStreamURL(self):
        self.api.wget.request( self.playlistURL() )
        for e in self.api.wget.select('asx entry ref'):
            url = e['href']
            if '/reklama/' not in url and '/upoutavky/' not in url:
                return url
        raise Exception("StreamURL not found!\nContent: " 
                            + self.api.wget.content)


class CzechtvPlugin(BasePlugin):
    """ CzechTV plugin class """
    BASE_URL = "http://www.ceskatelevize.cz"


    @plugin_folder
    def root(self):
        """ plugin root folder """
        self.core.setSorting('NONE')
        yield PFolder(u'Nově přidaná videa', call='news')
        yield PFolder(u'Nejsledovanější videa týdne', call='mostVisited')
        yield PFolder(u'Pořady podle abecedy', call='listByName')
        yield PFolder(u'Pořady podle data vysílání', call='dateList')
        yield PFolder(u'Pořady podle žánrů', call='listByGenre')


    @plugin_folder
    def news(self, path='/ivysilani/nejnovejsi/'):
        """ list newest videos """
        self.core.setSorting('NONE')

        url = self.BASE_URL + path
        self.wget.request(url)

        for item in self.wget.select('#bottomBlock div.item'):
            title_a = item.select_first('.title a')
            info = {
                    'title': title_a.text.strip(),
                    'plotoutline': item.select_first('p.title + p').text.strip(),
                }
            # add date 
            m = RE_DATE.search( info['plotoutline'] )
            if m:
                info['date'] = m.group(1)
            # add rating value: 
            m = RE_RATING.search( item.select_first('.programmeItemRatingStarMini')['style'] )
            if m:
                info['rating'] = float(m.group(1)) / 100.0
            # label 
            label = info['title']
            if info['plotoutline']:
                label += ' - ' + info['plotoutline']
        
            yield PItem(
                    label   = label,
                    call    = 'play',
                    param   = {'path': title_a['href']},
                    info    = info,
                    iconURL = item.select_first('.foto img')['src'],
                )


    @plugin_folder
    def mostVisited(self):
        """ list most visited videos """
        self.news(path='/ivysilani/nejsledovanejsi/')


    @plugin_folder
    def listByName(self, listID='programmeAlphabet'):
        """ List alphabet links """
        self.core.setSorting('NONE')

        url = self.BASE_URL + '/ivysilani/podle-abecedy/'
        self.wget.request(url)

        for a in self.wget.select("ul#%s li a" % listID):
            href = a.get('href')
            if href and '-vse' not in href:
                yield PFolder( a.text.strip(), call='listPrograms', \
                                param={'path': href})


    @plugin_folder
    def listByGenre(self):
        """ list genre links """
        self.listByName(listID='programmeGenre')


    @plugin_folder
    def listPrograms(self, path):
        """ List programs on given path """
        self.core.setSorting('NONE')

        url = self.BASE_URL + path
        self.wget.request(url)

        for a in self.wget.select("#programmeAlphabetContent a"):
            info = {
                    'title': a.text.strip(),
                    'plotoutline': a.get('title', '').strip(),
                }
            # label:
            label = info['title']
            if info['plotoutline']:
                label += ' - ' + info['plotoutline']
            yield PFolder(
                    label   = label,
                    call    = 'listEpizodes',
                    param   = {'path': a['href']},
                    info    = info,
                )


    @plugin_folder
    def listEpizodes(self, path):
        """ List program epizodes or bonuses """
        self.core.setSorting('NONE')
        
        prog = CzechTVProgram(self, path)
        epizodes = list( prog.getEpizodeList() )
        pages = prog.getPageLinks()

        # Add link to next page:
        if epizodes and pages.get('next'):
            if pages.get('next'):
                next_num = get_pg_num( pages['next'] )
                last_num = get_pg_num( pages['last'] )
                yield PFolder(u'Další strana (%s z %s)' % (next_num, last_num),
                                call='listEpizodes',
                                param={'path': pages['next']}
                            )

        # Add link to bonuses:
        if prog.bonusyPath:
            yield PFolder('Bonusy',
                        call='listEpizodes', 
                        param={'path': prog.bonusyPath}
                    )

        if epizodes:
            for item in epizodes:
                yield item
        else:
            item = prog.getInfo()
            if item:
                yield item


    @plugin_folder
    def dateList(self, date=None):
        """ Date-list for "list program by date" """
        self.core.setSorting('NONE')

        if date:
            date = datetime.date( *time.strptime(date, DATE_FORMAT)[:3] )
        else:
            date = datetime.date.today()

        # Add link to previous month virtual folder 
        pdate = date - datetime.timedelta(days=30)
        yield PFolder(u'Předchozí měsíc (%s)' % date2label(pdate),
                        call = 'dateList',
                        param = {'date': pdate.strftime(DATE_FORMAT)}
                    )
                
        for i in range(0, 30):
            pdate = date - datetime.timedelta(i)
            yield PFolder(date2label(pdate),
                        call = 'dayChannelList',
                        param = {'date': pdate.strftime(DATE_FORMAT)}
                    )


    @plugin_folder
    def dayChannelList(self, date):
        """ List channels for "list program by date" """
        self.core.setSorting('NONE')

        url = self.BASE_URL + '/ivysilani/podle-data-vysilani/' + date
        self.wget.request(url)
        
        icons = self.wget.select('#programDate .program-column .logo img')
        for i in range(0, len(icons)):
            img = icons[i]
            yield PFolder(img['alt'].strip(),
                        call = 'dayProgramList',
                        param = {'date': date, 'chnum': i},
                        iconURL = img['src']
                    )


    @plugin_folder
    def dayProgramList(self, date, chnum ):
        """ List programs on given channel ID and date """
        self.core.setSorting('NONE')

        url = self.BASE_URL + '/ivysilani/podle-data-vysilani/' + date
        self.wget.request(url)

        cols = self.wget.select('#programDate .program-column')
        chColumn = cols[ int(chnum) ]

        for item in chColumn.select('li.active'):
            title_a = item.select_first('.title a')
            info = {
                    'path': title_a['href'],
                    'title': title_a.text.strip(),
                    'time': item.select_first('.time').text.strip(),
                    'date': date,
                    'plotoutline': '',
                }
            desc = item.select_first('span.hrefGrayLight')
            if desc:
                info['plotoutline'] = desc.text.strip()
            # add rating value: 
            m = RE_RATING.search( item.select_first('.programmeItemRatingStarMini')['style'] )
            if m:
                info['rating'] = float(m.group(1)) / 100.0
            # label 
            label = info['time'] + ' - ' + info['title']
            if info['plotoutline']:
                label += ' - ' + info['plotoutline']
            yield PItem(label,
                        call = 'play',
                        param = {'path': title_a['href']},
                        info = info
                    )


    @plugin_call
    def play(self, path):
        """ Play stream on given path """
        # prepare program path
        stype = ('WM3','WM2','WM1')[ int(self.core.getSetting('quality')) ]
        path += "?streamtype=" + stype

        self.debug('get_program_info on path: ' + repr(path))
        prog = CzechTVProgram(self, path)
        infoItem = prog.getInfo()

        if not infoItem:
            self.core.okDialog('CzechTV plugin error',
                    u'Vybraná část není v iVysílání k dispozici.')
            return

        streamURL = prog.getStreamURL()
        self.debug('play_stream %s' % repr(streamURL))
        self.core.play(streamURL, infoItem)


